

PM_FUNC_NORM_ATTRIB NumToName( LIST_TYPES:iList, Int:iNum, String:szCopy[]="", Int:copyLen=0, bool:removeUnderScores=false, Int:playerID=0 )
{
	pokemod_funcstart_debug( "NumToName %d (List = %d)", iNum, iList );

	static String:szName[ NAME_LEN ];
	szName[0] = EOS;

	switch( iList )
	{
		case LIST_PLAYERS:
		{
			if ( PlayerGetInfo( iNum, PINFO_CONNECT ) )
			{
				get_user_name( iNum, szName, charsmax(szName) );
			}
		}
		case LIST_POKEMON:
		{
			if ( 0 <= iNum < ArraySize( g_iPokemonNames ) )
			{
				ArrayGetString( g_iPokemonNames, iNum, szName, charsmax(szName) );
			}
		}
		case LIST_POKEMON_NICKNAMES:
		{
			if ( 0 <= iNum < POKEMON_PER_PLAYER )
			{
				copy( szName, charsmax(szName), g_szPlayerPokemonNames[ playerID ][ iNum ] );
			}
		}
		case LIST_ITEMS:
		{
			if ( 0 <= iNum < ArraySize( g_iItemNames ) )
			{
				ArrayGetString( g_iItemNames, iNum, szName, charsmax(szName) );
			}
		}
		case LIST_LOCATIONS:
		{
			if ( 0 <= iNum < ArraySize( g_iLocationNames ) )
			{
				ArrayGetString( g_iLocationNames, iNum, szName, charsmax(szName) );
			}
		}
		case LIST_SKILLS:
		{
			if ( 0 <= iNum < ArraySize( g_iSkillNames ) )
			{
				ArrayGetString( g_iSkillNames, iNum, szName, charsmax(szName) );
			}
		}
		case LIST_STATUS:
		{
			if ( STATUS_NONE < PM_STATUS:iNum < PM_STATUS )
			{
				copy( szName, charsmax(szName), szStatusEffect[ PM_STATUS:iNum ] );
			}
		}
		case LIST_POKETYPE:
		{
			for ( new Int:iType, Int:iLen; iType < sizeof(szTypeName); iType++ )
			{
				if ( iNum & ( 1 << iType ) )
				{
					iLen += formatex( szName, charsmax(szName), "%s ", szTypeName[ iType ] );
				}
			}
			trim( szName );
		}
		case LIST_STAT:
		{
			if ( STAT_NULL < PM_STAT:iNum < PM_STAT )
			{
				copy( szName, charsmax(szName), gPlayerStatNames[ PM_STAT:iNum ] );
			}
		}
		default:
		{
			pokemod_debug( "Invalid List(%d) for NumToName", iList );
		}
	}

	if ( szName[0] == EOS )
		copy( szName, charsmax(szName), "None" );

	if ( removeUnderScores )
		replace_all( szName, charsmax(szName), "_", "" );

	if ( copyLen )
		copy( szCopy, copyLen, szName );

	pokemod_funcend_debug( "NumToName %s", szName );

	return szName;
}

PM_FUNC_NORM_ATTRIB any:NameToNum( LIST_TYPES:iList, String:szName[], Int:playerID = 0, &LIST_TYPES:typeReturn = LIST_NONE )
{
	pokemod_funcstart_debug( "NameToNum %s (List = %d)", szName, iList );

	static String:szNameCopy[ NAME_LEN ];
	copy( szNameCopy, charsmax(szNameCopy), szName );
	replace_all( szNameCopy, charsmax(szNameCopy), " ", "" );
	new Int:iNameLen = strlen( szNameCopy );

	//If we don't have a string to check, don't check it against anything
	if ( iNameLen <= 0 )
	{
		pokemod_funcend_debug( "NameToNum No Name" );
		return -1;
	}

	static String:szCompareName[ NAME_LEN ];
	new Int:iSimilarChars, Int:iHighestSimilar = 1;

	new Array:matches = ArrayCreate( 1, 1 );
	new Array:matchNames = ArrayCreate( NAME_LEN, 1 );

	if ( iList & LIST_PLAYERS )
	{
		if ( szNameCopy[0] == '#' )
		{
			new Int:iUserID = str_to_num( szNameCopy[1] );
			LoopThroughPlayersFlags( iTempPlayer, PLAYER_FLAGS_NOHLTV )
			{
				if ( get_user_userid( iTempPlayer ) == iUserID )
				{
					ArrayPushCell( matches, iTempPlayer );
					ArrayPushCell( matches, LIST_PLAYERS );
					ArrayPushString( matchNames, szCompareName );
				}
			}
		}
		else
		{
			LoopThroughPlayersFlags( iTempPlayer, PLAYER_FLAGS_NOHLTV )
			{
				get_user_name( iTempPlayer, szCompareName, charsmax(szCompareName) );

				iSimilarChars = NameCompare( szNameCopy, iNameLen, szCompareName );
				if ( iSimilarChars > iHighestSimilar )
				{
					ArrayClear( matches );
					ArrayClear( matchNames );
					iHighestSimilar = iSimilarChars;
				}
				if ( iSimilarChars == iHighestSimilar )
				{
					ArrayPushCell( matches, iTempPlayer );
					ArrayPushCell( matches, LIST_PLAYERS );
					ArrayPushString( matchNames, szCompareName );
				}
			}
		}
	}
	if ( iList & LIST_POKEMON )
	{
		if ( TrieKeyExists( g_iPokemonTrie, szNameCopy ) )
		{
			new Int:iPokeID;
			TrieGetCell( g_iPokemonTrie, szNameCopy, iPokeID );
			ArrayPushCell( matches, iPokeID );
			ArrayPushCell( matches, LIST_POKEMON );
			ArrayPushString( matchNames, szNameCopy );
		}
		else
		{
			for ( new Int:iPokeID = 1, Int:iSize = ArraySize( g_iPokemonNames );
				iPokeID < iSize;
				iPokeID++
			){
				ArrayGetString( g_iPokemonNames, iPokeID, szCompareName, charsmax(szCompareName) );

				iSimilarChars = NameCompare( szNameCopy, iNameLen, szCompareName );
				if ( iSimilarChars > iHighestSimilar )
				{
					ArrayClear( matches );
					ArrayClear( matchNames );
					iHighestSimilar = iSimilarChars;
				}
				if ( iSimilarChars == iHighestSimilar )
				{
					ArrayPushCell( matches, iPokeID );
					ArrayPushCell( matches, LIST_POKEMON );
					ArrayPushString( matchNames, szCompareName );
				}
			}
		}
	}
	if ( iList & LIST_POKEMON_NICKNAMES && PlayerGetInfo( playerID, PINFO_CONNECT ) )
	{
		for ( new String:szPokeName[ NAME_LEN ], Int:iPokeID, Int:iPokeNum = 0;
			iPokeNum < POKEMON_PER_PLAYER;
			iPokeNum++
		){
			copy( szCompareName, charsmax(szCompareName), g_szPlayerPokemonNames[ playerID ][ iPokeNum ] );

			iSimilarChars = NameCompare( szNameCopy, iNameLen, szCompareName );
			if ( iSimilarChars > iHighestSimilar )
			{
				ArrayClear( matches );
				ArrayClear( matchNames );
				iHighestSimilar = iSimilarChars;
			}
			if ( iSimilarChars == iHighestSimilar )
			{
				ArrayPushCell( matches, iPokeNum );
				ArrayPushCell( matches, LIST_POKEMON_NICKNAMES );
				ArrayPushString( matchNames, szCompareName );
			}

			iPokeID = g_iPlayerPokemonStats[ playerID ][ iPokeNum ][ POKESTAT_POKEMON ];
			if ( iPokeID <= 0 )
				continue;

			ArrayGetString( g_iPokemonNames, iPokeID, szPokeName, charsmax(szPokeName) );
			if ( !equali( szCompareName, szPokeName ) )
			{
				iSimilarChars = NameCompare( szNameCopy, iNameLen, szPokeName );
				if ( iSimilarChars > iHighestSimilar )
				{
					ArrayClear( matches );
					ArrayClear( matchNames );
					iHighestSimilar = iSimilarChars;
				}
				else if ( iSimilarChars == iHighestSimilar && ArraySize( matchNames ) == 1 )
				{
					if ( ArrayGetCell( matches, 0 ) == iPokeNum )
					{
						continue;
					}
				}

				if ( iSimilarChars == iHighestSimilar )
				{
					ArrayPushCell( matches, iPokeNum );
					ArrayPushCell( matches, LIST_POKEMON_NICKNAMES );
					ArrayPushString( matchNames, szPokeName );
				}
			}
		}
	}
	if ( iList & LIST_ITEMS )
	{
		if ( TrieKeyExists( g_iItemTrie, szNameCopy ) )
		{
			new Int:iItemID;
			TrieGetCell( g_iItemTrie, szNameCopy, iItemID );
			ArrayPushCell( matches, iItemID );
			ArrayPushCell( matches, LIST_ITEMS );
			ArrayPushString( matchNames, szNameCopy );
		}
		else
		{
			for ( new Int:iItemID, Int:iSize = ArraySize( g_iItemNames );
				iItemID < iSize;
				iItemID++
			){
				ArrayGetString( g_iItemNames, iItemID, szCompareName, charsmax(szCompareName) );

				iSimilarChars = NameCompare( szNameCopy, iNameLen, szCompareName );
				if ( iSimilarChars > iHighestSimilar )
				{
					ArrayClear( matches );
					ArrayClear( matchNames );
					iHighestSimilar = iSimilarChars;
				}
				if ( iSimilarChars == iHighestSimilar )
				{
					ArrayPushCell( matches, iItemID );
					ArrayPushCell( matches, LIST_ITEMS );
					ArrayPushString( matchNames, szCompareName );
				}
			}
		}
	}
	if ( iList & LIST_LOCATIONS )
	{
		if ( TrieKeyExists( g_iLocationTrie, szNameCopy ) )
		{
			new Int:iLocationID;
			TrieGetCell( g_iLocationTrie, szNameCopy, iLocationID );
			ArrayPushCell( matches, iLocationID );
			ArrayPushCell( matches, LIST_LOCATIONS );
			ArrayPushString( matchNames, szNameCopy );
		}
		else
		{
			for ( new Int:iLocationID, Int:iSize = ArraySize( g_iLocationNames );
				iLocationID < iSize;
				iLocationID++
			){
				ArrayGetString( g_iLocationNames, iLocationID, szCompareName, charsmax(szCompareName) );

				iSimilarChars = NameCompare( szNameCopy, iNameLen, szCompareName );
				if ( iSimilarChars > iHighestSimilar )
				{
					ArrayClear( matches );
					ArrayClear( matchNames );
					iHighestSimilar = iSimilarChars;
				}
				if ( iSimilarChars == iHighestSimilar )
				{
					ArrayPushCell( matches, iLocationID );
					ArrayPushCell( matches, LIST_LOCATIONS );
					ArrayPushString( matchNames, szCompareName );
				}
			}
		}
	}
	if ( iList & LIST_SKILLS )
	{
		if ( TrieKeyExists( g_iSkillTrie, szNameCopy ) )
		{
			new Int:iSkillID;
			TrieGetCell( g_iSkillTrie, szNameCopy, iSkillID );
			ArrayPushCell( matches, iSkillID );
			ArrayPushCell( matches, LIST_SKILLS );
			ArrayPushString( matchNames, szNameCopy );
		}
		else
		{
			for ( new Int:iSkillID, Int:iSize = ArraySize( g_iSkillNames );
				iSkillID < iSize;
				iSkillID++
			){
				ArrayGetString( g_iSkillNames, iSkillID, szCompareName, charsmax(szCompareName) );

				iSimilarChars = NameCompare( szNameCopy, iNameLen, szCompareName );
				if ( iSimilarChars > iHighestSimilar )
				{
					ArrayClear( matches );
					ArrayClear( matchNames );
					iHighestSimilar = iSimilarChars;
				}
				if ( iSimilarChars == iHighestSimilar )
				{
					ArrayPushCell( matches, iSkillID );
					ArrayPushCell( matches, LIST_SKILLS );
					ArrayPushString( matchNames, szCompareName );
				}
			}
		}
	}
	if ( iList & LIST_STATUS )
	{
		for ( new PM_STATUS:iStatusNum;
			iStatusNum < PM_STATUS;
			iStatusNum++
		){
			copy( szCompareName, charsmax(szCompareName), szStatusEffect[ iStatusNum ] );

			iSimilarChars = NameCompare( szNameCopy, iNameLen, szCompareName );
			if ( iSimilarChars > iHighestSimilar )
			{
				ArrayClear( matches );
				ArrayClear( matchNames );
				iHighestSimilar = iSimilarChars;
			}
			if ( iSimilarChars == iHighestSimilar )
			{
				ArrayPushCell( matches, iStatusNum );
				ArrayPushCell( matches, LIST_SKILLS );
				ArrayPushString( matchNames, szCompareName );
			}
		}
	}
	if ( iList & LIST_POKETYPE )
	{
		for ( new Int:iType;
			iType < sizeof(szTypeName);
			iType++
		){
			copy( szCompareName, charsmax(szCompareName), szTypeName[ iType ] );

			iSimilarChars = NameCompare( szNameCopy, iNameLen, szCompareName );
			if ( iSimilarChars > iHighestSimilar )
			{
				ArrayClear( matches );
				ArrayClear( matchNames );
				iHighestSimilar = iSimilarChars;
			}
			if ( iSimilarChars == iHighestSimilar )
			{
				ArrayPushCell( matches, ( 1 << iType ) );
				ArrayPushCell( matches, LIST_TYPES );
				ArrayPushString( matchNames, szCompareName );
			}
		}
	}
	if ( iList & LIST_STAT )
	{
		for ( new PM_STAT:iStatNum;
			iStatNum < PM_STAT;
			iStatNum++
		){
			copy( szCompareName, charsmax(szCompareName), gPlayerStatNames[ iStatNum ] );

			iSimilarChars = NameCompare( szNameCopy, iNameLen, szCompareName );
			if ( iSimilarChars > iHighestSimilar )
			{
				ArrayClear( matches );
				ArrayClear( matchNames );
				iHighestSimilar = iSimilarChars;
			}
			if ( iSimilarChars == iHighestSimilar )
			{
				ArrayPushCell( matches, iStatNum );
				ArrayPushCell( matches, LIST_STAT );
				ArrayPushString( matchNames, szCompareName );
			}
		}
	}

	new Int:iNumReturn = -1;

	new Int:iMatchNum = ArraySize( matchNames );
	switch( iMatchNum )
	{
		case 0:
		{
			if ( playerID )
			{
				client_print( playerID, print_chat, "No matches found for ^"%s^".", szName );
			}
		}
		case 1:
		{
			iNumReturn = ArrayGetCell( matches, 0 );
			typeReturn = LIST_TYPES:ArrayGetCell( matches, 1 );
		}
		default:
		{
			if ( playerID )
			{
				const iShownMatches = 3;
				new String:szMatchList[ NAME_LEN * iShownMatches ], Int:iLen;

				for ( new Int:iMatch, Int:iSize = min( iMatchNum, iShownMatches );
					iMatch < iSize;
					iMatch++
				){
					ArrayGetString( matchNames, iMatch, szMatchList[ iLen ], charsmax(szMatchList) - iLen );

					if ( iMatch < iSize - 1 )
					{
						add( szMatchList, charsmax(szMatchList), ", " );
					}
					else if ( iMatchNum > iShownMatches )
					{
						add( szMatchList, charsmax(szMatchList), ", ..." );
						break;
					}

					iLen = strlen( szMatchList );
				}

				client_print( playerID, print_chat, "%d matches found for ^"%s^". (%s)", iMatchNum, szName, szMatchList );
			}
		}
	}

	ArrayDestroy( matches );
	ArrayDestroy( matchNames );

	pokemod_funcend_debug( "NameToNum %d", iNumReturn );

	return iNumReturn;
}

PM_FUNC_NORM_ATTRIB NameCompare( const String:szName[], const Int:len, const String:szCompared[ NAME_LEN ], const bool:caseSensitive=false )
{
	static String:szCompareString[ sizeof szCompared ];
	copy( szCompareString, charsmax(szCompareString), szCompared );
	replace_all( szCompareString, charsmax(szCompareString), " ", "" );

	for ( new Int:i; i <= len; i++ )
	{
		if ( szCompareString[ i ] == EOS )
			return i + 1;
		if ( szName[ i ] == EOS )
			return i;
		if ( caseSensitive ?
			( szName[ i ] != szCompareString[ i ] ) :
			( tolower( szName[ i ] ) != tolower( szCompareString[ i ] ) )
		)
			return i;
	}
	return len;
}

PM_FUNC_NORM_ATTRIB CoreCallValues( iVictim = 0, iAttacker = 0, Float:fDamage = 0.0, iDamageBits = 0, iWeaponID = 0, iHitZone = 0, Float:fSpeed = 0.0, bool:bRestore = false )
{
	new iValues[ 7 ];

	static Array:iLastValues = Invalid_Array;
	if ( iLastValues == Invalid_Array )
		iLastValues = ArrayCreate( sizeof( iValues ), 1 );

	if ( bRestore )
	{
		new Int:iSize = ArraySize( iLastValues );
		if ( iSize )
		{
			ArrayGetArray( iLastValues, iSize-1, iValues );
			ArrayDeleteItem( iLastValues, iSize-1 );
		}

		g_iVictim =		iValues[ 0 ];
		g_iAttacker =	iValues[ 1 ];
		g_fDamage =		Float:iValues[ 2 ];
		g_iDamageBits =	iValues[ 3 ];
		g_iWeaponID =	iValues[ 4 ];
		g_iHitZone =	iValues[ 5 ];
		g_fSpeed =		Float:iValues[ 6 ];
	}
	else
	{
		iValues[ 0 ] = g_iVictim;
		iValues[ 1 ] = g_iAttacker;
		iValues[ 2 ] = _:g_fDamage;
		iValues[ 3 ] = g_iDamageBits;
		iValues[ 4 ] = g_iWeaponID;
		iValues[ 5 ] = g_iHitZone;
		iValues[ 6 ] = _:g_fSpeed;

		ArrayPushArray( iLastValues, iValues );

		g_iVictim = iVictim;
		g_iAttacker = iAttacker;
		g_fDamage = fDamage;
		g_iDamageBits = iDamageBits;
		g_iWeaponID = iWeaponID;
		g_iHitZone = iHitZone;
		g_fSpeed = fSpeed;
	}
}

PM_FUNC_NORM_ATTRIB Chance( Int:iPercentChance )
{
	new const iChanceMultOffset = 100;
	return random( 100 * iChanceMultOffset ) <= ( iPercentChance * iChanceMultOffset );
}




